home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Extensions… / Confidential ƒ / Confidential.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  11.1 KB  |  402 lines  |  [TEXT/MPS ]

  1. /*________________________________________________________
  2.  
  3.     File: Confidential.c
  4.  
  5.     C code for a printing extension that stamps a message
  6.     on each page spooled.
  7.  
  8.     Dave Hersey
  9.     Apple Developer Technical Support
  10.  
  11.     2/01/93  - dmh - Completely rewrote for the a5 seed.
  12.     4/26/93  - dmh - Renamed files for b1 seed.
  13.     4/27/93  - dmh - Updated NewSpoolPage override to work
  14.                      w/o CopyDeepToShape.
  15.     9/05/93  - dmh - Updated for b2.
  16.              - removed work-around for a 1.0a5
  17.                panel bug.  That should have been
  18.                removed in the b1 version…  oops.
  19.              - Fixed minor bug with panel's editText
  20.                fields' highlighting.
  21.              - Switched to Exception.h assertion stuff
  22.                for error checking.
  23.    12/18/93  - dmh - Updated for b3.
  24.     3/22/94  - dmh - Updated for b4.
  25.  
  26.     (Note: all functions are in the Mark menu.)
  27.     
  28. __________________________________________________________*/
  29.  
  30. #include "Confidential.h"
  31.  
  32.  
  33. /*******************************************************************
  34.     __Startup__ contains our jump table to the overrides.
  35.     
  36. ********************************************************************/
  37. #if defined(__MWERKS__)
  38. asm void __Startup__(void) ;
  39. asm void __Startup__(void)
  40. {
  41.     DC.L        0                // GX needs this
  42.  
  43.     JMP        NewJobPrintDialog    // (offset =  4)
  44.     JMP        NewHandlePanelEvent    // (offset =  8)
  45.     JMP        NewSpoolPage        // (offset = 12)
  46.     
  47.     RTS                            // this is needed so __Startup__ symbol works
  48. }
  49. #endif
  50.  
  51.  
  52. /*******************************************************************
  53.     NewJobPrintDialog is our override for GXJobPrintDialog.  All we
  54.     do is set up our panel and then forward the message.
  55.     
  56. ********************************************************************/
  57.  
  58. OSErr NewJobPrintDialog(gxDialogResult *dlogResult)
  59. {
  60.     OSErr    err;
  61.     
  62.     err = SetUpPrintPanel();
  63.  
  64.     if (!err)
  65.         err = Forward_GXJobPrintDialog(dlogResult);
  66.     
  67.     return err;
  68. }
  69.  
  70.  
  71. /*******************************************************************
  72.     NewHandlePanelEvent is our override for GXHandlePanelEvent. If
  73.     the event is one of ours, we handle it.  Otherwise, we just
  74.     forward it down the chain.
  75.     
  76. ********************************************************************/
  77.  
  78. OSErr NewHandlePanelEvent(gxPanelInfoRecord *panelInfo)
  79. {
  80.     GrafPtr            oldPort;
  81.     DialogPtr        pDlg;
  82.  
  83. // Get a pointer to the dialog, save our current grafPort,
  84. // and set us to the dialog's port.
  85.  
  86.     pDlg = panelInfo->pDlg;
  87.     GetPort(&oldPort);
  88.     SetPort(pDlg);
  89.  
  90.     switch (panelInfo->panelEvt)
  91.     {
  92.  
  93. // If our panel is activating/deactivating or if the focus (which
  94. // section of the dialog is active) has changed we need to activate
  95. // our editText fields appropriately.
  96.  
  97.         case gxPanelActivateEvt:            // The panel is becoming active.
  98.         case gxPanelDeactivateEvt:            // The panel is becoming inactive.
  99.         case gxPanelIconFocusEvt:            // The user is moving to the icon list.
  100.         case gxPanelPanelFocusEvt:            // The user is moving to the panel.
  101.  
  102.             if ((((DialogPeek) pDlg)->editField +1) == (panelInfo->itemCount +d_message) ||
  103.                 (((DialogPeek) pDlg)->editField +1) == (panelInfo->itemCount +d_fontSize))
  104.             {
  105.                 if (panelInfo->panelEvt == gxPanelPanelFocusEvt)
  106.                     TEActivate(((DialogPeek) pDlg)->textH);
  107.                 else
  108.                     TEDeactivate(((DialogPeek) pDlg)->textH);
  109.             }
  110.             break;
  111.     }
  112.  
  113. // Restore the original port as we leave.
  114.  
  115.     SetPort(oldPort);
  116.     return noErr;
  117. }
  118.  
  119.  
  120. /*******************************************************************
  121.     NewSpoolPage is our override for the GXSpoolPage message.  We
  122.     check to see if we're enabled, and if so, add the desired text
  123.     shape to the page before forwarding.
  124.     
  125. ********************************************************************/
  126.  
  127. OSErr NewSpoolPage(gxSpoolFile spFile, gxFormat aFormat, gxShape pgShape)
  128. {
  129.     OSErr                err;
  130.     long                idx, numParts;
  131.     StampCollection        stampConfig;
  132.     Boolean                addedStamp = false;
  133.     gxShape                msgShapeRef, shapeRef = nil;
  134.  
  135. //    Load our stamp collection item.
  136.  
  137.     err = GetStamp(&stampConfig);
  138.     require((err != collectionItemNotFoundErr), NoStampSetUp);
  139.     nrequire(err, CouldNotGetStamp);
  140.  
  141.  
  142. // If the stamp is turned on, add the text to the page shape, and keep a
  143. // reference to it so we make sure we remove the correct picture item on
  144. // exit.  We must return the picture as we received it.
  145.  
  146.     if (stampConfig.stampEnabled)
  147.     {
  148.         err = AddStampToPage(&stampConfig, pgShape, aFormat);
  149.         nrequire(err, CouldNotAddStamp);
  150.  
  151.         addedStamp = true;
  152.         GXGetPictureParts(pgShape, 1, 1, &msgShapeRef, nil, nil, nil);
  153.     }
  154.  
  155.  
  156. // Forward the GXSpoolPage message on to other handlers.
  157.  
  158. NoStampSetUp:
  159.  
  160.     err = Forward_GXSpoolPage(spFile, aFormat, pgShape);
  161.     require(addedStamp, DidNotAddStamp);
  162.  
  163.  
  164. // If we added a stamp, we now have to remove it from the original picture.
  165. // Our stamp should be the first shape in the picture, but it's possible that
  166. // an incorrectly written printing extension below us has changed the picture
  167. // and not undone its deed.  To be extra sure that we remove the correct item,
  168. // we compare each shape reference in the picture with the reference of our
  169. // stamp shape.  If/when we find the stamp, we remove the shape from the
  170. // picture.  Finally, if an error didn't occur during forwarding, we make one
  171. // last stab at finding a problem to report.
  172.  
  173.     numParts = GXGetPicture(pgShape, nil, nil, nil, nil);
  174.  
  175.     for (idx = 1; (shapeRef != msgShapeRef) && (idx <= numParts); idx++)
  176.     {
  177.         GXGetPictureParts(pgShape, idx, 1, &shapeRef, nil, nil, nil);
  178.  
  179.         if (shapeRef == msgShapeRef)
  180.             GXSetPictureParts(pgShape, idx, 1, 0, nil, nil, nil, nil);
  181.     }
  182.  
  183.     if (!err)
  184.         err = (OSErr) GXGetGraphicsError(nil);
  185.  
  186. CouldNotGetStamp:
  187. CouldNotAddStamp:
  188. DidNotAddStamp:
  189.  
  190.     return err;
  191. }
  192.  
  193.  
  194. /*******************************************************************
  195.     AddStampToPage adds our text stamp to the page shape passed.
  196.     
  197. ********************************************************************/
  198.  
  199. OSErr AddStampToPage(StampCollection *stampConfig, gxShape pgShape, gxFormat aFormat)
  200. {
  201.     gxGraphicsError        aGrphErr;
  202.     gxRectangle            pBounds;
  203.     gxShape                msgShape;
  204.     gxPoint                textCtr;
  205.     Fixed                cx, cy;
  206.     gxColor                msgColor;
  207.     gxFormat            curFormat;
  208.  
  209. // Create a new text shape to add to the page, based on what's in our
  210. // collection item.
  211.  
  212.     msgShape = GXNewText((long) stampConfig->message[0],
  213.                          (const unsigned char *) &stampConfig->message[1], nil);
  214.  
  215.  
  216. // If no errors, set the shape's colorspace to gxGraySpace and color it
  217. // light gray.  Set the font's size as appropriate.
  218.  
  219.  
  220.     aGrphErr = GXGetGraphicsError(nil);
  221.     nrequire(aGrphErr, CouldNotCreateText);
  222.     
  223.     msgColor.space = gxGraySpace;
  224.     msgColor.profile = nil;
  225.     msgColor.element.gray = 190 <<8;
  226.     GXSetShapeColor(msgShape, &msgColor);
  227.     GXSetShapeTextSize(msgShape, ff(stampConfig->fontSize));
  228.  
  229.  
  230. // If no errors, get the dimensions of the format's page size.  Remember
  231. // that the format passed to us may be nil, so use the job's format in
  232. // that case.
  233.  
  234.     GXGetGraphicsError(&aGrphErr);
  235.     nrequire(aGrphErr, CouldNotSetUpText);
  236.  
  237.     curFormat = (aFormat != nil)? aFormat: GXGetJobFormat(GXGetJob(), 1);
  238.     GXGetFormatDimensions(curFormat, &pBounds, nil);
  239.  
  240.  
  241. // If no errors, get the page and the text shape's center and move the text
  242. // so that it's centered on the page.
  243.  
  244.     aGrphErr = (gxGraphicsError) GXGetJobError(GXGetJob());
  245.     nrequire(aGrphErr, CouldNotAccessFormat);
  246.  
  247.     cx = pBounds.left + (pBounds.right - pBounds.left) >>1;
  248.     cy = pBounds.top + (pBounds.bottom - pBounds.top) >>1;
  249.     GXGetShapeCenter(msgShape, 0, &textCtr);
  250.     GXMoveShapeTo(msgShape, cx -textCtr.x, cy -textCtr.y);
  251.  
  252.  
  253. // Rotate the stamp about its (new) center point 45° and add it to the
  254. // beginning of the picture so that it draws behind the printed
  255. // information.  Note that you can call GXSetPictureParts(pgShape, 0, 0, 1…)
  256. // to place the text *on top* of everything on the page.
  257.  
  258.     GXGetShapeCenter(msgShape, 0, &textCtr);
  259.     GXSetShapeAttributes(msgShape,
  260.                          GXGetShapeAttributes(msgShape) | gxMapTransformShape);
  261.  
  262.     GXRotateShape(msgShape, ff(45), textCtr.x, textCtr.y);
  263.  
  264.     GXSetPictureParts(pgShape, 1, 0, 1, &msgShape, nil, nil, nil);
  265.     GXGetGraphicsError(&aGrphErr);
  266.  
  267.  
  268. // Dispose of the text shape on the way out.
  269.  
  270. CouldNotAccessFormat:
  271. CouldNotSetUpText:
  272.  
  273.     GXDisposeShape(msgShape);
  274.  
  275. CouldNotCreateText:
  276.  
  277.     return (OSErr) aGrphErr;
  278. }
  279.  
  280.  
  281. /*******************************************************************
  282.     SetUpPrintPanel sets up our print panel, adding a default
  283.     StampCollection item to the job collection.  This collection
  284.     item has the values we'll use to set up our panel's controls.
  285.     
  286. ********************************************************************/
  287.  
  288. OSErr SetUpPrintPanel()
  289. {
  290.     OSErr                    err;
  291.     gxPanelSetupRecord        panelSetupRec;
  292.     StampCollection            stampConfig;
  293.     Boolean                    newItem = false;
  294.  
  295. // Try to find our collection item.
  296.  
  297.     err = GetCollectionItem(GXGetJobCollection(GXGetJob()),
  298.                             kStampCollectionType,
  299.                             gxPrintingTagID,
  300.                             nil,
  301.                             &stampConfig);
  302.  
  303.  
  304. // If we don't have an item in the job collection yet, store our default
  305. // settings in it.
  306.  
  307.     if (err == collectionItemNotFoundErr)
  308.     {
  309.         err = GetDefaultSettings(&stampConfig);
  310.  
  311.         if (!err)
  312.             err = AddCollectionItem(GXGetJobCollection(GXGetJob()),
  313.                                     kStampCollectionType,
  314.                                     gxPrintingTagID,
  315.                                     sizeof(StampCollection),
  316.                                     &stampConfig);
  317.  
  318.         nrequire(err, HaveCollectionMgrError);
  319.     }
  320.  
  321.  
  322. // Now, do the actual panel set up.
  323.  
  324.     panelSetupRec.panelResId        = r_stampPanel;        // which panel resource?
  325.     panelSetupRec.resourceRefNum    = GXGetMessageHandlerResFile(); // where is it?
  326.     panelSetupRec.refCon            = 0;                // we don't use this.
  327.     panelSetupRec.panelKind            = gxExtensionPanel;    // This is an extension panel.
  328.  
  329.     err = GXSetupDialogPanel(&panelSetupRec);
  330.  
  331.  
  332. HaveCollectionMgrError:
  333.  
  334.     return err;
  335. }
  336.  
  337.  
  338. /*******************************************************************
  339.     GetJobCollectionItem is a generic routine that retrieves a
  340.     collection item from the job collection.
  341.     
  342. ********************************************************************/
  343.  
  344. OSErr GetJobCollectionItem(void *collectItem, long *collectSize,
  345.                            OSType collectType, short collectID)
  346. {
  347.     return GetCollectionItem(GXGetJobCollection(GXGetJob()),
  348.                              collectType,
  349.                              collectID,
  350.                              collectSize,
  351.                              collectItem);
  352. }
  353.  
  354.  
  355. /*******************************************************************
  356.     GetDefaultSettings returns a StampCollection item with default
  357.     settings from our extension's resource file.
  358.     
  359. ********************************************************************/
  360.  
  361. OSErr GetDefaultSettings(StampCollection *stampConfig)
  362. {
  363.     OSErr    err;
  364.     short    oldResFile;
  365.     Str255    fontSizeStr;
  366.  
  367. // Save the current resource file and get our extension's.
  368.  
  369.     oldResFile = CurResFile();
  370.     UseResFile(GXGetMessageHandlerResFile());
  371.     
  372.  
  373. // Now set up the default settings in the structure passed.
  374.  
  375.     stampConfig->stampEnabled = false;
  376.     GetIndString(stampConfig->message, r_str, r_defaultStrIdx);
  377.     err = ResError();
  378.     nrequire(err, CouldNotLoadString);
  379.  
  380.     GetIndString(fontSizeStr, r_str, r_defaultFSizeIdx);
  381.     StringToNum(fontSizeStr, &stampConfig->fontSize);
  382.     err = ResError();
  383.  
  384. // Restore the original resource file and exit.
  385.  
  386. CouldNotLoadString:
  387.     
  388.     UseResFile(oldResFile);
  389.     return err;
  390. }
  391.  
  392.  
  393. /*******************************************************************
  394.     GetStamp returns a StampCollection item, if there's one set up.
  395.     
  396. ********************************************************************/
  397.  
  398. OSErr GetStamp(StampCollection *stampConfig)
  399. {
  400.     return GetJobCollectionItem(stampConfig, nil, kStampCollectionType, gxPrintingTagID);
  401. }
  402.